package com.corpgovernment.supplier.service;

import com.corpgovernment.api.messageadvice.enums.MsgBizType;
import com.corpgovernment.api.organization.model.message.SendMsgRequest;
import com.corpgovernment.api.organization.model.user.login.PtUserLoginType;
import com.corpgovernment.api.supplier.metadata.EMsgTemp;
import com.corpgovernment.api.supplier.vo.AtUserLoginVo;
import com.corpgovernment.api.supplier.vo.request.AtUserLoginRequest;
import com.corpgovernment.api.supplier.vo.response.AtSelUserResponse;
import com.corpgovernment.api.supplier.vo.response.AtUserLoginResponse;
import com.corpgovernment.common.apollo.OrganizationApollo;
import com.corpgovernment.common.base.AbstractBaseService;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.base.CommonException;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.holder.TenantContextHolder;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.corpgovernment.common.utils.Md5Util;
import com.corpgovernment.common.utils.ObjectUtils;
import com.corpgovernment.common.utils.PasswordRegUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.producer.MessageEventProducer;
import com.corpgovernment.organization.service.IUserLoginService;
import com.corpgovernment.redis.cache.RedisUtils;
import com.corpgovernment.supplier.common.DefExample;
import com.corpgovernment.supplier.converter.AtUserLoginConverter;
import com.corpgovernment.supplier.entity.db.AtUserLogin;
import com.corpgovernment.supplier.mapper.AtUserLoginMapper;
import com.ctrip.corp.obt.auth.client.handler.token.JwtTokenHandler;
import com.ctrip.corp.obt.auth.core.token.OAuth2AccessToken;
import com.ctrip.corp.obt.generic.core.context.TenantContext;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.ExceptionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Slf4j
@Service
public class AtUserLoginService extends AbstractBaseService {

    @Autowired
    private AtUserLoginMapper atUserLoginMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private MessageEventProducer messageEventProducer;
    @Autowired
    private OrganizationApollo organizationApollo;
    @Autowired
    private IUserLoginService userLoginService;
    @Autowired
    private JwtTokenHandler jwtTokenHandler;


    public void insert(AtUserLoginVo model) {
        if (model == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PARAMS_NULL);
        }
        if (StringUtils.isBlank(model.getSupplierCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        if (StringUtils.isBlank(model.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.UID_NULL);
        }
        if (StringUtils.isBlank(model.getPwd())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_NULL);
        }
        List<AtUserLogin> list = atUserLoginMapper.list(new AtUserLogin(model.getSupplierCode(), model.getUid()));
        if (list == null || list.size() == 0) {
            AtUserLogin userLogin = ObjectUtils.copyProperties(model, AtUserLogin.class);
            userLogin.setIsAdmin(model.getIsAdmin());
            userLogin.setPwd(getPwd(model.getSupplierCode(), model.getUid(), model.getPwd()));
            userLogin.setDatachangeCreatetime(new Date());
            atUserLoginMapper.insert(userLogin);
        } else {
            log.info("已经存在管理员，不能更改！oldInfo：" + JsonUtils.toJsonString(list) + ",newInfo:" + JsonUtils.toJsonString(model));
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_SPECIFICATION_ERROR);
        }
    }

    public AtUserLogin insertOrUpdate(AtUserLogin ul) {
        Example e = new DefExample(AtUserLogin.class);
        String supplierCode = ul.getSupplierCode();
        String uid = ul.getUserId();
        e.createCriteria().andEqualTo("supplierCode", supplierCode).andEqualTo("userId", uid);
        AtUserLogin old = atUserLoginMapper.selectOneByExample(e);
        if (old == null) {
            if (!PasswordRegUtils.checkPasswordComplexity(ul.getPwd())) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_FORMAT_ERROR);
            }
            ul.setPwd(getPwd(ul.getSupplierCode(), ul.getUserId(), ul.getPwd()));
            atUserLoginMapper.insertSelective(ul);
            return ul;
        } else {
            ul.setId(ul.getId());
            atUserLoginMapper.updateByPrimaryKeySelective(ul);
            return ul;
        }
    }

    public AtUserLoginVo getBySupplierCode(String supplierCode) {
        if (StringUtils.isBlank(supplierCode)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        List<AtUserLogin> list = atUserLoginMapper.list(new AtUserLogin(supplierCode));
        if (list == null || list.size() == 0) {
            return null;
        }
        return ObjectUtils.copyProperties(list.get(0), AtUserLoginVo.class);
    }

    public AtUserLoginResponse login(AtUserLoginRequest request) {
        String clientId = TenantContext.getClientId();
        if (clientId == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.CLIENT_ID_NULL);
        }
        if (StringUtils.isBlank(request.getSupplierCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        if (StringUtils.isBlank(request.getPwd())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_NULL);
        }
        if (StringUtils.isBlank(request.getUserId())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.UID_NULL);
        }
        Map<String, String> principal = new HashMap<>();
        principal.put("supplierCode", request.getSupplierCode());
        principal.put("userId", request.getUserId());
        OAuth2AccessToken oAuth2AccessToken = ExceptionUtils.catchThrow(() -> jwtTokenHandler.createAccessTokenByPwd(clientId, principal, request.getPwd(), false, Collections.singletonMap("source", "SUPPLIER")), exception -> new CommonException(exception.getMessage()));
        log.info("create access token info:{} by pwd", com.ctrip.corp.obt.generic.utils.JsonUtils.toJsonString(oAuth2AccessToken));
        Map<String, Object> userInfoByAccessToken = ExceptionUtils.catchThrow(() -> jwtTokenHandler.getUserInfoByAccessToken(clientId, oAuth2AccessToken.getValue()), exception -> new CommonException(exception.getMessage()));
        BaseUserInfo userInfo = com.ctrip.corp.obt.generic.utils.JsonUtils.convert(userInfoByAccessToken, BaseUserInfo.class);
        return successLogin(userInfo, oAuth2AccessToken);
    }

    public Map<String, String> getMsgCode(AtUserLoginRequest request) {
        if (StringUtils.isBlank(request.getPhoneNum())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NULL);
        }
        if (StringUtils.isBlank(request.getSupplierCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        List<AtUserLogin> list = getByPhone(request.getSupplierCode(), request.getPhoneNum());
        if (list == null || list.size() == 0) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        String msgCode = genMsgCode();
        log.info("发送绑定手机号验证码 phoneNum={},msgCode={}", request.getPhoneNum(), msgCode);
        sendVerifySms(request.getCountryCode(), request.getPhoneNum(), msgCode);
        AtUserLogin userLogin = new AtUserLogin();
        userLogin.setPhoneNum(request.getPhoneNum());
        userLogin.setSupplierCode(request.getSupplierCode());
        userLogin.setMsgCode(msgCode);
        String idCode = Md5Util.encodeMd5WithRandomSalt(msgCode);
        redisUtils.setCache(EMsgTemp.LOGIN.getKey(idCode), userLogin, organizationApollo.getAtMsgTimeOut() * 60);
        Map<String, String> map = new HashMap<>();
        map.put("idCode", idCode);
        return map;
    }

    public AtUserLoginResponse validateMsgCode(AtUserLoginRequest request) {
        if (StringUtils.isBlank(request.getRandomMsg())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.RANDOM_NULL);
        }
        if (StringUtils.isBlank(request.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_NULL);
        }
        log("validateMsgCode", request.getRandomMsg(), request.getMsgCode());
        AtUserLogin userLoginTemp = redisUtils.getCache(EMsgTemp.LOGIN.getKey(request.getRandomMsg()), AtUserLogin.class);
        if (userLoginTemp == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_EXPIRE);
        }
        log.info("验证登录密码。" + userLoginTemp);
        if (!request.getMsgCode().equals(userLoginTemp.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_ERROR);
        }
        List<AtUserLogin> list = getByPhone(userLoginTemp.getSupplierCode(), userLoginTemp.getPhoneNum());
        if (list == null || list.size() == 0) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        List<AtUserLogin> userLoginTempList = new ArrayList<>();
        List<AtSelUserResponse> selUsers = new ArrayList<>();
        for (AtUserLogin userLogin : list) {
            userLoginTempList.add(userLogin);
            AtSelUserResponse selUserResponse = new AtSelUserResponse();
            selUserResponse.setSupplierCode(userLogin.getSupplierCode());
            selUserResponse.setUserId(userLogin.getUserId());
            selUserResponse.setUserName(userLogin.getUserName());
            selUsers.add(selUserResponse);
        }
        if (userLoginTempList.size() == 1) {
            AtUserLoginResponse response = successLogin(userLoginTempList.get(0));
            response.setSelUsers(selUsers);
            return response;
        } else {
            AtUserLoginResponse response = new AtUserLoginResponse();
            response.setSelUsers(selUsers);
            String selToken = Md5Util.encodeMd5WithRandomSalt(Md5Util.genRandomStr() + request.getPwd());
            response.setSelToken(selToken);
            redisUtils.setCache(EMsgTemp.LOGIN_SEL_TOKEN.getKey(selToken), userLoginTempList, organizationApollo.getAtMsgTimeOut() * 60);
            log.info("用户登录多账户 selToken=" + selToken);
            return response;
        }

    }

    public AtUserLoginResponse confirmUid(AtUserLoginRequest request) {
        if (StringUtils.isBlank(request.getSelToken())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SEL_TOKEN_NULL);
        }
        if (StringUtils.isBlank(request.getSelUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SEL_UID_NULL);
        }
        List<AtUserLogin> userLoginTempList = redisUtils.getCacheList(EMsgTemp.LOGIN_SEL_TOKEN.getKey(request.getSelToken()), AtUserLogin.class);
        if (userLoginTempList == null || userLoginTempList.size() == 0) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SELECTED_TIME_OUT);
        }
        for (AtUserLogin userLogin : userLoginTempList) {
            if (request.getSelUid().equals(userLogin.getUserId())) {
                return successLogin(userLogin);
            }
        }
        throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
    }

    public Map<String, String> validatePwd(BaseUserInfo userInfo, AtUserLoginRequest request) {
        if (StringUtils.isBlank(userInfo.getSupplierCode()) || StringUtils.isBlank(userInfo.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_NOT_LOGIN);
        }
        if (StringUtils.isBlank(request.getPwd())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_NULL);
        }
        AtUserLogin userLogin = getByUserId(userInfo.getSupplierCode(), userInfo.getUid());
        if (userLogin == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        String pwd = getPwd(userInfo.getSupplierCode(), userInfo.getUid(), request.getPwd());
        if (!userLogin.getPwd().equals(pwd)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_SPECIFICATION_ERROR);
        }
        String validateToken = Md5Util.encodeMd5WithRandomSalt(Md5Util.genRandomStr() + genMsgCode());
        redisUtils.setCache(validateToken, userLogin, organizationApollo.getAtMsgTimeOut() * 60);
        Map<String, String> map = new HashMap<>();
        map.put("validateToken", validateToken);
        return map;
    }

    public AtUserLoginResponse updatePwd(BaseUserInfo userInfo, AtUserLoginRequest request) {
        if (StringUtils.isBlank(userInfo.getSupplierCode()) || StringUtils.isBlank(userInfo.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_NOT_LOGIN);
        }
        if (StringUtils.isBlank(request.getValidateToken())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.VALIDATE_TOKEN_IS_NULL);
        }
        if (StringUtils.isBlank(request.getNewPwd())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_NULL);
        }
        AtUserLogin userLogin = redisUtils.getCache(request.getValidateToken(), AtUserLogin.class);
        if (userLogin == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        String pwd = getPwd(userInfo.getSupplierCode(), userInfo.getUid(), request.getNewPwd());

        AtUserLogin param = new AtUserLogin();
        param.setSupplierCode(userInfo.getSupplierCode());
        param.setUserId(userInfo.getUid());
        param.setPwd(pwd);

        atUserLoginMapper.updatePwd(param);
        return null;
    }

    public Map<String, String> getResetPwdCode(AtUserLoginRequest request) {
        if (StringUtils.isBlank(request.getPhoneNum())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NULL);
        }
        if (StringUtils.isBlank(request.getSupplierCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        List<AtUserLogin> list = getByPhone(request.getSupplierCode(), request.getPhoneNum());
        if (list == null || list.size() == 0) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        String msgCode = genMsgCode();
        log.info("发送重置手机号验证码 phoneNum={},msgCode={}", request.getPhoneNum(), msgCode);
        if (!sendSmsMsg(request.getPhoneNum(), request.getCountryCode(), msgCode)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SMS_SEND_ERROR);
        }
        AtUserLogin userLogin = new AtUserLogin();
        userLogin.setPhoneNum(request.getPhoneNum());
        userLogin.setSupplierCode(request.getSupplierCode());
        userLogin.setMsgCode(msgCode);
        String idCode = Md5Util.encodeMd5WithRandomSalt(msgCode);
        redisUtils.setCache(EMsgTemp.RESET.getKey(idCode), userLogin, organizationApollo.getAtMsgTimeOut() * 60);
        Map<String, String> map = new HashMap<>();
        map.put("idCode", idCode);
        map.put("vCode", msgCode);
        return map;
    }

    public AtUserLoginResponse validateResetPwdCode(AtUserLoginRequest request) {
        if (StringUtils.isBlank(request.getRandomMsg())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.RANDOM_NULL);
        }
        if (StringUtils.isBlank(request.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_NULL);
        }
        log("validateResetPwdCode", request.getRandomMsg(), request.getMsgCode());
        AtUserLogin userLoginTemp = redisUtils.getCache(EMsgTemp.RESET.getKey(request.getRandomMsg()), AtUserLogin.class);
        if (userLoginTemp == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_EXPIRE);
        }
        log.info("验证重置密码。" + userLoginTemp);
        if (!request.getMsgCode().equals(userLoginTemp.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_ERROR);
        }
        List<AtUserLogin> list = getByPhone(userLoginTemp.getSupplierCode(), userLoginTemp.getPhoneNum());
        if (list == null || list.size() == 0) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }

        List<AtUserLogin> userLoginTempList = new ArrayList<>();
        List<AtSelUserResponse> selUsers = new ArrayList<>();
        for (AtUserLogin userLogin : list) {
            userLoginTempList.add(userLogin);
            AtSelUserResponse selUserResponse = new AtSelUserResponse();
            selUserResponse.setSupplierCode(userLogin.getSupplierCode());
            selUserResponse.setUserId(userLogin.getUserId());
            selUserResponse.setUserName(userLogin.getUserName());
            selUsers.add(selUserResponse);
        }
        AtUserLoginResponse response = new AtUserLoginResponse();
        response.setSelUsers(selUsers);
        String selToken = Md5Util.encodeMd5WithRandomSalt(Md5Util.genRandomStr() + request.getPwd());
        response.setSelToken(selToken);
        redisUtils.setCache(EMsgTemp.RESET.getKey(selToken), userLoginTempList, organizationApollo.getAtMsgTimeOut() * 60);
        log.info("重置密码多账户 selToken=" + selToken);
        return response;
    }

    public AtUserLoginResponse resetPwd(AtUserLoginRequest request) {
        if (StringUtils.isBlank(request.getSelToken())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SEL_TOKEN_NULL);
        }
        if (StringUtils.isBlank(request.getPwd())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PASSWORD_NULL);
        }
        List<AtUserLogin> list = redisUtils.getCacheList(EMsgTemp.RESET.getKey(request.getSelToken()), AtUserLogin.class);
        if (list == null || list.size() == 0) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_EXPIRE);
        }
        for (AtUserLogin userLogin : list) {
            AtUserLoginResponse response = successLogin(userLogin);
            AtUserLogin param = new AtUserLogin();
            param.setSupplierCode(userLogin.getSupplierCode());
            param.setUserId(userLogin.getUserId());
            param.setPwd(getPwd(userLogin.getSupplierCode(), userLogin.getUserId(), request.getPwd()));
            atUserLoginMapper.updatePwd(param);
            return response;
        }
        throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
    }

    public AtUserLoginResponse getBindMsgCode(BaseUserInfo userInfo, AtUserLoginRequest request) {
        if (StringUtils.isBlank(userInfo.getSupplierCode()) || StringUtils.isBlank(userInfo.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_NOT_LOGIN);
        }
        if (StringUtils.isBlank(request.getPhoneNum())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NULL);
        }
        String msgCode = genMsgCode();
        log.info("发送绑定手机号验证码 phoneNum={},msgCode={}", request.getPhoneNum(), msgCode);
        sendVerifySms(request.getCountryCode(), request.getPhoneNum(), msgCode);

        AtUserLogin userLogin = new AtUserLogin();
        userInfo.setSupplierCode(userInfo.getSupplierCode());
        userInfo.setUid(userInfo.getUid());
        userLogin.setMsgCode(msgCode);
        redisUtils.setCache(EMsgTemp.BIND.getKey(userInfo.getSupplierCode() + "_" + userInfo.getUid() + "_" + request.getPhoneNum()), userLogin, organizationApollo.getAtMsgTimeOut() * 60);

        return null;
    }

    public AtUserLoginResponse submitBindPhone(BaseUserInfo userInfo, AtUserLoginRequest request) {
        if (StringUtils.isBlank(userInfo.getSupplierCode()) || StringUtils.isBlank(userInfo.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_NOT_LOGIN);
        }
        if (StringUtils.isBlank(request.getPhoneNum())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NULL);
        }
        if (StringUtils.isBlank(request.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_NULL);
        }
        AtUserLogin userLogin = redisUtils.getCache(EMsgTemp.BIND.getKey(userInfo.getSupplierCode() + "_" + userInfo.getUid() + "_" + request.getPhoneNum()), AtUserLogin.class);
        if (userLogin == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_EXPIRE);
        }
        if (!request.getMsgCode().equals(userLogin.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_ERROR);
        }
        AtUserLogin param = new AtUserLogin();
        param.setSupplierCode(userInfo.getSupplierCode());
        param.setUserId(userInfo.getUid());
        param.setPhoneNum(request.getPhoneNum());
        atUserLoginMapper.updatePhone(param);
        return null;
    }

    public AtUserLoginRequest getUnbindMsgCode(BaseUserInfo userInfo) {
        if (StringUtils.isBlank(userInfo.getSupplierCode()) || StringUtils.isBlank(userInfo.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_NOT_LOGIN);
        }
        AtUserLogin userLogin = getByUserId(userInfo.getSupplierCode(), userInfo.getUid());
        if (userLogin == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        if (StringUtils.isBlank(userLogin.getPhoneNum())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        String msgCode = genMsgCode();
        log.info("发送解绑手机号验证码 phoneNum={},msgCode={}", userLogin.getPhoneNum(), msgCode);
        sendVerifySms(userLogin.getCountryCode(), userLogin.getPhoneNum(), msgCode);
        userLogin.setMsgCode(msgCode);
        redisUtils.setCache(EMsgTemp.UNBIND.getKey(userInfo.getSupplierCode() + "_" + userInfo.getUid()), userLogin, organizationApollo.getAtMsgTimeOut() * 60);
        return null;
    }

    public AtUserLoginResponse submitUnBindPhone(BaseUserInfo userInfo, AtUserLoginRequest request) {
        if (StringUtils.isBlank(userInfo.getSupplierCode()) || StringUtils.isBlank(userInfo.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.USER_NOT_LOGIN);
        }
        if (StringUtils.isBlank(request.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_NULL);
        }
        AtUserLogin userLogin = redisUtils.getCache(EMsgTemp.UNBIND.getKey(userInfo.getSupplierCode() + "_" + userInfo.getUid()), AtUserLogin.class);
        if (userLogin == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_EXPIRE);
        }
        if (!request.getMsgCode().equals(userLogin.getMsgCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.MSGCODE_ERROR);
        }
        AtUserLogin param = new AtUserLogin();
        param.setSupplierCode(userInfo.getSupplierCode());
        param.setUserId(userInfo.getUid());
        atUserLoginMapper.updateUnBindPhone(param);
        return null;
    }

    private String genMsgCode() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(new Random().nextInt(10));
        }
        return sb.toString();
    }

    private String getPwd(String suppplierCode, String userId, String pwd) {
        return Md5Util.getDeepMd5Msg(suppplierCode + "_" + userId, pwd);
    }

    private AtUserLoginResponse successLogin(BaseUserInfo userLogin, OAuth2AccessToken oAuth2AccessToken) {
        AtUserLoginResponse response = new AtUserLoginResponse();
//        response.setPhoneNum(userLogin.getPhoneNum());
        response.setSupplierCode(userLogin.getSupplierCode());
        response.setUserId(userLogin.getUid());
        response.setUserName(userLogin.getUserName());

        List<String> menuList = new ArrayList<>();
        menuList.add("busineseOrderManage_flightOrder");
        menuList.add("busineseOrderManage_intlFlightOrder");
        menuList.add("busineseOrderManage_trainOrder");
        menuList.add("busineseOrderManage_hotelOrder");
        menuList.add("busineseOrderManage_carOrder");
        menuList.add("busineseOrderManage_travelOrder");
        menuList.add("businessProcess_orderMonitor");
        menuList.add("reportDownload_travel");
        menuList.add("reportDownload_flight");
        menuList.add("reportDownload_intlflight");
        menuList.add("reportDownload_hotel");
        menuList.add("reportDownload_car");
        menuList.add("reportDownload_group");
        menuList.add("reportDownload_train");
        menuList.add("accountManager_accountConfig");
        menuList.add("accountManager_roleConfig");
        response.setMenuList(menuList);
        response.setRefreshToken(oAuth2AccessToken.getRefreshToken().getValue());
        response.setToken(oAuth2AccessToken.getValue());
        return response;
    }

    private AtUserLoginResponse successLogin(AtUserLogin userLogin) {
        AtUserLoginResponse response = new AtUserLoginResponse();
        response.setPhoneNum(userLogin.getPhoneNum());
        response.setSupplierCode(userLogin.getSupplierCode());
        response.setUserId(userLogin.getUserId());
        response.setUserName(userLogin.getUserName());

        List<String> menuList = new ArrayList<>();
        menuList.add("busineseOrderManage_flightOrder");
        menuList.add("busineseOrderManage_intlFlightOrder");
        menuList.add("busineseOrderManage_trainOrder");
        menuList.add("busineseOrderManage_hotelOrder");
        menuList.add("busineseOrderManage_carOrder");
        menuList.add("busineseOrderManage_travelOrder");
        menuList.add("businessProcess_orderMonitor");
        menuList.add("reportDownload_travel");
        menuList.add("reportDownload_flight");
        menuList.add("reportDownload_intlflight");
        menuList.add("reportDownload_hotel");
        menuList.add("reportDownload_car");
        menuList.add("reportDownload_group");
        menuList.add("reportDownload_train");
        menuList.add("accountManager_accountConfig");
        menuList.add("accountManager_roleConfig");
        response.setMenuList(menuList);

        String token = Md5Util.encodeMd5WithRandomSalt(userLogin.getSupplierCode() + "_" + userLogin.getUserId() + "_" + userLogin.getPwd());

        response.setToken(token);

        BaseUserInfo userInfo = new BaseUserInfo();
        userInfo.setToken(token);
        userInfo.setUserName(userLogin.getUserName());
        userInfo.setUid(userLogin.getUserId());
        userInfo.setSupplierCode(userLogin.getSupplierCode());
        userInfo.setSupplierLoginId(userLogin.getId());
        userInfo.setIsAdmin(userLogin.getIsAdmin());
        userInfo.setSource("SUPPLIER");
        userInfo.setTenantId(TenantContextHolder.getTenantId());
        log.info("用户信息，BaseUserInfo:{}", JsonUtils.toJsonString(userInfo));
        redisUtils.setCache("SUPPLIER:" + token, userInfo, 60 * 60 * 24 * 30 * 3);
        return response;
    }

    public List<AtUserLogin> list(PtUserLoginType ptUserLoginType) {
        if (StringUtils.isBlank(ptUserLoginType.getSupplierCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        AtUserLogin param = new AtUserLogin();
        param.setSupplierCode(ptUserLoginType.getSupplierCode());
        param.setUserId(ptUserLoginType.getUserId());
        param.setPhoneNum(ptUserLoginType.getPhoneNum());
        param.setStatus(1);
        List<AtUserLogin> userLoginList = atUserLoginMapper.list(param);
        if (CollectionUtils.isEmpty(userLoginList)) {
            log.info("用户不存在supplierCode[{}] ptUserLoginType[{}]", param.getSupplierCode(), ptUserLoginType);
            return Collections.emptyList();
        }
        return userLoginList;
    }

    private AtUserLogin getByUserId(String supplierCode, String userId) {
        if (StringUtils.isBlank(supplierCode)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        if (StringUtils.isBlank(userId)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.UID_IS_NULL);
        }
        AtUserLogin param = new AtUserLogin();
        param.setSupplierCode(supplierCode);
        param.setUserId(userId);
        param.setStatus(1);
        List<AtUserLogin> list = atUserLoginMapper.list(param);
        if (list == null || list.size() == 0) {
            log.info("用户不存在supplierCode[{}] userId[{}]", supplierCode, userId);
            return null;
        }
        return list.get(0);
    }

    private List<AtUserLogin> getByPhone(String supplierCode, String phoneNum) {
        if (StringUtils.isBlank(supplierCode)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        if (StringUtils.isBlank(phoneNum)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NULL);
        }
        if (phoneNum.length() > 11) {
            return null;
        }
        AtUserLogin param = new AtUserLogin();
        param.setSupplierCode(supplierCode);
        param.setPhoneNum(phoneNum);
        param.setStatus(1);
        List<AtUserLogin> list = atUserLoginMapper.list(param);
        if (list == null || list.size() == 0) {
            log.info("用户不存在supplierCode[{}] phoneNum[{}]", supplierCode, phoneNum);
            return null;
        }
        return list;
    }

    private void sendVerifySms(String countryCode, String phoneNum, String verifyCode) {
        log.info("发送登录相关短信phoneNum[{}] verifyCode[{}]", phoneNum, verifyCode);
        if (StringUtils.isBlank(phoneNum)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NULL);
        }
        if (phoneNum.length() != 11) {
            log.error("手机号不为11位" + phoneNum);
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_LENGTH_NULL);
        }
        Long count = redisUtils.increment(EMsgTemp.LOGIN_MSG_TEMP.getKey(phoneNum));
        if (count == 1L) {
            redisUtils.setExpire(EMsgTemp.LOGIN_MSG_TEMP.getKey(phoneNum), 60 * 60 * 24);
        }
        log.info("手机号[" + phoneNum + "] count[" + count + "]");
        if (count > organizationApollo.getAtMsgMaxCount()) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.OUT_AT_MSG_MAX_COUNT, phoneNum);
        }
        messageEventProducer.sendMessageEvent(MsgBizType.UNIVERSAL_VERIFICATION_CODE, countryCode, phoneNum, Collections.singletonMap("code", verifyCode));
    }

    public boolean sendSmsMsg(String phoneNum, String countryCode, String randomCode) {
        Boolean flag = userLoginService.sendSmsMsg(new SendMsgRequest(randomCode, phoneNum, countryCode));
        if (!flag) {
            log.error("Sms send failed. Msg:{} phone:{}, countryCode:{}, randomCode:{}", false, phoneNum, countryCode, randomCode);
        }
        return flag;
    }

    public JSONResult saveOrUpdateUserLogin(AtUserLoginVo model) {
        if (model == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PARAMS_NULL);
        }
        if (StringUtils.isBlank(model.getSupplierCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
        }
        if (StringUtils.isBlank(model.getUid())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.UID_NULL);
        }
        if (model.getStatus() == null) {
            model.setStatus(1);
        }
        AtUserLogin ul = atUserLoginMapper.loadUserLogin(model.getUid(), model.getSupplierCode());
        if (ul != null) {
            Long id = ul.getId();
            //修改
            try {
                //ConvertUtils.register(new DateConverter(null), Date.class);
                BeanUtils.copyProperties(ul, model);
            } catch (Exception e) {
                log.error("属性拷贝失败", e);
                throw new CorpBusinessException(OrganizationResponseCodeEnum.BEAN_COPY_ERROR);
            }
            // 老代码的坑
            ul.setId(id);
            ul.setUserId(model.getUid());
            ul.setDatachangeLasttime(new Date());
            atUserLoginMapper.updateByPrimaryKeySelective(ul);
        } else {
            //新增
            AtUserLogin userLogin = ObjectUtils.copyProperties(model, AtUserLogin.class);
            Date date = new Date();
            // 老代码的坑
            userLogin.setUserId(model.getUid());
            userLogin.setIsDeleted(false);
            userLogin.setDatachangeCreatetime(date);
            userLogin.setDatachangeLasttime(date);
            userLogin.setPwd(getPwd(model.getSupplierCode(), model.getUid(), model.getPwd()));
            atUserLoginMapper.insert(userLogin);
        }
        return JSONResult.ok();
    }

    public AtUserLoginVo getUserLogin(AtUserLoginVo model) {
        AtUserLogin userLogin = atUserLoginMapper.getAtUserLogin(model);
        if (userLogin == null) {
            return null;
        }
        try {
            return AtUserLoginConverter.INSTANCE.convert(userLogin);
        } catch (Exception e) {
            log.error("AtUserLoginConverter failed.", e);
        }
        return model;
    }

    public JSONResult delUserLogin(AtUserLoginVo model) {
        AtUserLogin userLogin = ObjectUtils.copyProperties(model, AtUserLogin.class);
        atUserLoginMapper.deleteAtUserLogin(userLogin);
        return JSONResult.ok();
    }

    public void delUserLoginBySupplierCode(String supplierCode) {
        Example e = new Example(AtUserLogin.class);
        e.createCriteria().andEqualTo("supplierCode", supplierCode);
        AtUserLogin record = new AtUserLogin();
        record.setIsDeleted(true);
        atUserLoginMapper.updateByExampleSelective(record, e);
    }

    /**
     * 根据uid和supplierCode查询当前用户
     *
     * @param uid
     * @param supplierCode
     * @return
     */
    public AtUserLogin loadUserLogin(String uid, String supplierCode) {
        return atUserLoginMapper.loadUserLogin(uid, supplierCode);
    }

    /**
     * 更新账号
     *
     * @param atUserLogin
     */
    public void updatePwd(AtUserLogin atUserLogin) {
        atUserLoginMapper.updatePwd(atUserLogin);
    }
}
